💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    전체 흐름 Part6 | ✅저자: 이유정(박사)

    소스보기

    Tutorial 6: ViewSets & Routers에서는 기존의 뷰 클래스들을 ViewSet으로 통합하고, URL 구성을 DefaultRouter로 자동화하는 방식으로 변경되었습니다.

    UserViewSet, SnippetViewSet 추가 / 기존 뷰들 제거 (SnippetList, SnippetDetail, SnippetHighlight, UserList, UserDetail, api_root)

    snippets/views.py

    from rest_framework import viewsets, permissions, renderers
    from rest_framework.decorators import action
    from rest_framework.response import Response
    from django.contrib.auth.models import User
    from snippets.models import Snippet
    from snippets.serializers import SnippetSerializer, UserSerializer
    from snippets.permissions import IsOwnerOrReadOnly
    
    
    class UserViewSet(viewsets.ReadOnlyModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    
    class SnippetViewSet(viewsets.ModelViewSet):
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer
        permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
    
        @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
        def highlight(self, request, *args, **kwargs):
            snippet = self.get_object()
            return Response(snippet.highlighted)
    
        def perform_create(self, serializer):
            serializer.save(owner=self.request.user)
    

    🔹 UserViewSet

    class UserViewSet(viewsets.ReadOnlyModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    
    • 용도: 사용자 목록과 단일 사용자 정보를 읽기 전용(ReadOnly) 으로 제공
    • ReadOnlyModelViewSetlist()retrieve()만 제공하므로 사용자 생성/수정은 불가

    🔹 SnippetViewSet

    class SnippetViewSet(viewsets.ModelViewSet):
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer
        permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
    
    
    • 용도: 코드 스니펫에 대해 CRUD API 제공
    • ModelViewSetlist, create, retrieve, update, destroy 등을 자동 지원
    • permission_classes는:
      • 인증된 사용자만 쓰기 가능 (IsAuthenticatedOrReadOnly)
      • 오직 소유자만 수정/삭제 가능 (IsOwnerOrReadOnly: 커스텀 권한)

    🔹 커스텀 액션: highlight

    @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)
    
    
    • 기능: 특정 스니펫을 HTML 형식으로 하이라이트된 상태로 반환
    • URL 예: /snippets/1/highlight/
    • StaticHTMLRenderer 덕분에 HTML 응답을 반환함 (e.g., 하이라이트된 코드)

    🔹 객체 생성 시 소유자 자동 지정

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)
    
    

    기능: POST 요청으로 스니펫을 생성할 때 현재 요청한 유저를 owner로 자동 설정

    📌 관련 커스텀 권한 클래스 예시 (IsOwnerOrReadOnly)

    from rest_framework import permissions
    
    class IsOwnerOrReadOnly(permissions.BasePermission):
        def has_object_permission(self, request, view, obj):
            if request.method in permissions.SAFE_METHODS:
                return True
            return obj.owner == request.user
    
    

    용도: 읽기는 모두 허용, 수정/삭제는 객체의 소유자만 허용

    ✅ 전체 흐름 요약

    • /users/: 사용자 정보 조회
    • /snippets/: 코드 스니펫 CRUD
    • /snippets/{id}/highlight/: 특정 스니펫의 HTML 하이라이트 보기
    • 인증 없이 읽기는 가능, 쓰기는 인증 필요
    • 객체 소유자만 수정/삭제 가능

    기존 뷰 분기 방식 제거 → Router 기반 URL 자동 구성으로 변경

    snippets/urls.py

    from snippets import views
    
    from django.urls import path, include
    from rest_framework.routers import DefaultRouter
    
    router = DefaultRouter()
    router.register(r'snippets', views.SnippetViewSet, basename='snippet')
    router.register(r'users', views.UserViewSet, basename='user')
    
    urlpatterns = [
        path('', include(router.urls)),
    ]
    

    기존에 수동으로 정의했던 path('snippets/...'), path('users/...'), api_root 등은 모두 제거됨

    
    [test]
    http://127.0.0.1:8000/snippets/
    http://127.0.0.1:8000/snippets/1/
    http://127.0.0.1:8000/users/
    http://127.0.0.1:8000/users/1/
    http://127.0.0.1:8000/
    http://127.0.0.1:8000/snippets/1/highlight/
    
    
    TOP
    preload preload